package com.herench.bridge;

import com.herench.bs.utils.DataFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.ListIterator;
import java.util.UUID;

/**
 * Created by ThinkPad on 2017/11/14.
 */
public class StrangeMessage implements Serializable{

    private static final long serialVersionUID = -69984722837398103L;

    private Document body;
    private Element commitEl;
    private Element returnDataEl;
    private Element clientInfoEl;
    private Element serverInfoEl;
    private Element resultEl;
    private Date expires;
    private int resendTimes;


    public Document getBody() {
        return body;
    }

    public void setBody(Document body) {
        this.body = body;
    }

    public StrangeMessage() {
        this.body = DocumentHelper.createDocument();
        String timeString = DataFormatUtils.getTimeString(new Date());
        Element rootElement = DocumentHelper.createElement("BITCRoot");
        this.body.setRootElement(rootElement);
        this.commitEl = rootElement.addElement("CommitData");
        returnDataEl = rootElement.addElement("ReturnData");
        clientInfoEl = rootElement.addElement("ClientInfo");
        Element tempSubClientInfoEl = clientInfoEl.addElement("Info");
        tempSubClientInfoEl.addAttribute("METHOD","").addAttribute("TOKEN","").addAttribute("COMPANY_ID","").addAttribute("OPT_ID","").addAttribute("OPT_NAME","").addAttribute("OPT_SOURCE","").addAttribute("OPT_DEV_ID","").addAttribute("OPT_IP","").addAttribute("OPT_DATE",timeString).addAttribute("OPT_GUID","").addAttribute("OPT_ACCT",timeString);
        serverInfoEl = rootElement.addElement("ServerInfo");
        Element tempSubServiceInfoEl = serverInfoEl.addElement("Info");
        tempSubServiceInfoEl.addAttribute("DEV_ID","").addAttribute("DEV_IP","").addAttribute("DEV_DATE", timeString).addAttribute("DEV_GUID", UUID.randomUUID().toString()).addAttribute("DEV_ACCT", timeString);
        resultEl = rootElement.addElement("Result");
    }

    public StrangeMessage(String message) throws Exception {
        this.body = DocumentHelper.parseText(message);
        Element rootElement = body.getRootElement();
        commitEl = rootElement.element("CommitData");
        returnDataEl = rootElement.element("ReturnData");
        clientInfoEl = rootElement.element("ClientInfo");
        serverInfoEl = rootElement.element("ServerInfo");
        resultEl = rootElement.element("Result");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND,30);
        this.expires = calendar.getTime();
    }

    public void addAttrToClientInfo(String key, String value) {
        Element infoEl = this.clientInfoEl.element("Info");
        if (infoEl == null) {
            infoEl = this.clientInfoEl.addElement("Info");
        }
        infoEl.addAttribute(key.toUpperCase(), value);
    }

    public void addAttrToClientInfo(String key, String value,boolean isUpperCase) {
        Element infoEl = this.clientInfoEl.element("Info");
        if (infoEl == null) {
            infoEl = this.clientInfoEl.addElement("Info");
        }
        if (isUpperCase){
            infoEl.addAttribute(key.toUpperCase(), value);
        }else {
            infoEl.addAttribute(key, value);
        }
    }

    public String getAttrFromClientInfo(String key) {
        Element infoEl = this.clientInfoEl.element("Info");
        return infoEl.attributeValue(key.toUpperCase());
    }

    public String getAttrFromCommitDataRow(String key){
        try {
            Element dataRow = this.commitEl.element("Data").element("DataRow");
            return dataRow.attributeValue(key);
        } catch (Exception e) {
            throw new RuntimeException("提交参数异常");
        }
    }

    /**
     * 此方法仅用于data标签只有一行|否则会在所有datarow中设置此值
     *
     * @param key
     * @param value
     */
    public void addReturnData(String key, String value) {
        Element dataEl = this.returnDataEl.element("Data");
        if (dataEl == null) {
            dataEl = this.returnDataEl.addElement("Data");
        }
        ListIterator<Element> iterator = (ListIterator<Element>) dataEl.elementIterator("DataRow");
        if (iterator == null || !iterator.hasNext()) {
            addAttrToReturnData(key.toUpperCase(), value);
        } else {
            for (; iterator.hasNext(); ) {
                Element dataRowEl = iterator.next();
                dataRowEl.addAttribute(key.toUpperCase(), value);
            }
        }
    }

    public void addReturnDataRow(Element element) {
        Element dataEl = this.returnDataEl.element("Data");
        if (dataEl == null) {
            dataEl = this.returnDataEl.addElement("Data");
        }
        dataEl.add(element);
    }

    public void addAttrToReturnData(String key, String value) {
        Element dataEl = this.returnDataEl.element("Data");
        if (dataEl == null) {
            dataEl = this.returnDataEl.addElement("Data");
        }
        Element dataRowEl = dataEl.element("DataRow");
        if (dataRowEl == null) {
            dataRowEl = dataEl.addElement("DataRow");
        }
        dataRowEl.addAttribute(key.toUpperCase(), value);
    }

    public void addExecuteStatus(String executeStatus) {
        Element resultInfoEl = this.resultEl.element("Info");
        if (resultInfoEl == null) {
            resultInfoEl = this.resultEl.addElement("Info");
        }
        resultInfoEl.addAttribute("EXECUTE_STATUS", executeStatus);
    }

    public void addExecuteMessage(String executeMessage) {
        Element resultInfoEl = this.resultEl.element("Info");
        if (resultInfoEl == null) {
            resultInfoEl = this.resultEl.addElement("Info");
        }
        resultInfoEl.addAttribute("EXECUTE_MESSAGE", executeMessage);
    }

    public void addAttrToCommitData(String key,String value){
        Element dataEl = this.commitEl.element("Data");
        if (dataEl==null){
            dataEl = this.commitEl.addElement("Data");
        }
        Element dataRowEl = dataEl.element("DataRow");
        if (dataRowEl==null){
            dataRowEl = dataEl.addElement("DataRow");
        }
        dataRowEl.addAttribute(key.toUpperCase(),value);
    }


    public void addAttrToCommitData(String key, String value,  boolean isUpperCase) {
        Element dataEl = this.commitEl.element("Data");
        if (dataEl==null){
            dataEl = this.commitEl.addElement("Data");
        }
        Element dataRowEl = dataEl.element("DataRow");
        if (dataRowEl==null){
            dataRowEl = dataEl.addElement("DataRow");
        }
        if (isUpperCase){
            dataRowEl.addAttribute(key.toUpperCase(),value);
        }else {
            dataRowEl.addAttribute(key,value);
        }
    }

    public Date getExpires() {
        return expires;
    }


    public int getResendTimes() {
        return resendTimes;
    }

    public void resended() {
        this.resendTimes = this.resendTimes+1;
    }

    public boolean isAlive(){
        return this.expires.compareTo(new Date())>0;
    }

    @Override
    public String toString() {
        return this.body.asXML();
    }

}
